﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Mirror.Ia32
{
	public class IndexedOperand : Operand
	{
		public IndexedOperand(
			OperandSize size,
			SimpleOperand baseOperand,
			SimpleOperand indexOperand,
			int scale,
			long displacement,
			Register segmentOverride
			)
			:base(size)
		{
			if (baseOperand == null) throw new ArgumentNullException("baseOperand");
			//if (indexOperand == null) throw new ArgumentNullException("indexOperand");

			this.BaseOperand = baseOperand;
			this.IndexOperand = indexOperand;
			this.Scale = scale;
			this.Displacement = displacement;
			this.SegmentOverride = segmentOverride;
		}

		public SimpleOperand BaseOperand { get; private set; }
		public SimpleOperand IndexOperand { get; private set; }
		public int Scale { get; private set; }
		public long Displacement { get; private set; }
		public Register SegmentOverride { get; private set; }

		public override bool Equals(object obj)
		{
			IndexedOperand other = obj as IndexedOperand;
			if (other == null) return false;

			bool equal =
				(object.Equals(this.BaseOperand, other.BaseOperand))
				&& (object.Equals(this.IndexOperand, other.IndexOperand))
				&& (object.Equals(this.Scale, other.Scale))
				&& (object.Equals(this.Displacement, other.Displacement))
				&& (object.Equals(this.SegmentOverride, other.SegmentOverride))
				;

			return equal;
		}
		public override int GetHashCode()
		{
			int hash = 0;
			if (this.BaseOperand != null) hash ^= this.BaseOperand.GetHashCode();
			if (this.IndexOperand != null) hash ^= this.IndexOperand.GetHashCode();
			hash ^= this.Scale;
			hash ^= this.Displacement.GetHashCode();
			if (this.SegmentOverride != null) hash ^= this.SegmentOverride.GetHashCode();

			return hash;
		}
		public override string ToString()
		{
			StringBuilder builder = new StringBuilder();
			builder.Append("[");
			if (this.SegmentOverride != null)
			{
				builder.Append(this.SegmentOverride);
				builder.Append(":");
			}
			builder.Append(this.BaseOperand);
			if (this.IndexOperand != null)
			{
				builder.Append("+");
				builder.Append(this.IndexOperand);
				if (this.Scale != 1)
				{
					builder.Append("*");
					builder.Append(this.Scale);
				}
			}
			if (this.Displacement > 0)
			{
				builder.Append("+");
				builder.AppendFormat("0{0:X}h", this.Displacement);
			}
			else if (this.Displacement < 0)
			{
				builder.Append("-");
				builder.AppendFormat("0{0:X}h", -this.Displacement);
			}
			builder.Append("]");

			return builder.ToString();
		}
	}
}
